//
//  E7Rule.cpp
//  EndlessBattle
//
//  Created by cc on 12-3-20.
//  Copyright (c) 2012年 PalmGame. All rights reserved.
//

#include "E7Rule.h"

#include "E7Logic.h"

CE7Rule::CE7Rule()
{
    m_iWinnerID = -1 ;
}

CE7Rule::~CE7Rule()
{
}

bool CE7Rule::CheckCreateUnit(int countryid, int townid, eUnitValue unitvalue, int cellid)
{
//    printf("CE7Rule::CheckCreateUnit: [%d][%d][%d][%d]\n", countryid, townid, unitvalue, cellid) ;
    if (-1 == countryid || -1 == townid || -1 == unitvalue || -1 == cellid)
    {
        return false ;
    }

    if (UV_TOWER != unitvalue && UV_SOLDIER_1 != unitvalue && UV_SOLDIER_2 != unitvalue && UV_SOLDIER_3 != unitvalue)
    {
//        printf("CE7Rule::CheckCreateUnit: unitvalue [%d]\n", unitvalue) ;
        return false ;
    }

    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(cellid) ;
    if (NULL == pCell)
    {
        return false ;
    }

    CE7Town* pTown = s_pLogic->GetSelectTownInfo(townid) ;
    if (UNIT_NEED_GOLD_ARRAY[unitvalue] > pTown->GetGold())
    {
//        printf("CE7Rule::CheckCreateUnit: UNIT_NEED_GOLD_ARRAY[unitvalue] [%d] > [%d]\n",
//               UNIT_NEED_GOLD_ARRAY[unitvalue], pTown->GetGold()) ;
        return false ;
    }

    if (countryid != pCell->GetCountryID())
    {
//        printf("CE7Rule::CheckCreateUnit: countryid != pCell->GetCountryID() [%d]\n", pCell->GetCountryID()) ;
        return CheckAttackWithCreate(countryid, townid, unitvalue, cellid) ;
//        return false ;
    }
    else if (-1 != pCell->GetUnitID())
    {
//        printf("CE7Rule::CheckCreateUnit: pCell->GetUnitID() [%d]\n", pCell->GetUnitID()) ;
        if (townid != pCell->GetTownID())
        {
//            printf("CE7Rule::CheckCreateUnit: pCell->GetTownID() [%d]\n", pCell->GetTownID()) ;
            return false ;
        }

        CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(pCell->GetUnitID()) ;
        if (UV_SOLDIER_1 == pUnit->GetUV() && (UV_SOLDIER_1 == unitvalue || UV_SOLDIER_2 == unitvalue))
        {
            return true ;
        }
        
        if (UV_SOLDIER_2 == pUnit->GetUV() && (UV_SOLDIER_1 == unitvalue))
        {
            return true ;
        }

        // change unit.
        if (UV_TREE == pUnit->GetUV() || UV_STONE == pUnit->GetUV() || UV_DEAD == pUnit->GetUV())
        {
            if (UV_SOLDIER_1 == unitvalue || UV_SOLDIER_2 == unitvalue || UV_SOLDIER_3 == unitvalue)
            {
                return true ;
            }
        }

        return false ;
    }
    else
    {
        if (townid != pCell->GetTownID())
        {
//            printf("CE7Rule::CheckCreateUnit: pCell->GetTownID() [%d]\n", pCell->GetTownID()) ;
            return false ;
        }
    }

    return true ;
}

int CE7Rule::CreateUnit(int countryid, int townid, eUnitValue unitvalue, int cellid)
{
    int res = -1 ;

    if (!CheckCreateUnit(countryid, townid, unitvalue, cellid))
    {
        return res ;
    }

    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(cellid) ;
    if (countryid != pCell->GetCountryID())
    {
        res = AttackWithCreate(countryid, townid, unitvalue, cellid) ;
    }
    else if (-1 != pCell->GetUnitID())
    {
        CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(pCell->GetUnitID()) ;
        if (UV_SOLDIER_1 == pUnit->GetUV() && UV_SOLDIER_1 == unitvalue)
        {
            pUnit->SetUV(UV_SOLDIER_2) ;
        }
        else if (UV_SOLDIER_1 == pUnit->GetUV() && UV_SOLDIER_2 == unitvalue)
        {
            pUnit->SetUV(UV_SOLDIER_3) ;
        }
        else if (UV_SOLDIER_2 == pUnit->GetUV() && UV_SOLDIER_1 == unitvalue)
        {
            pUnit->SetUV(UV_SOLDIER_3) ;
        }
        else if (UV_TREE == pUnit->GetUV() || UV_STONE == pUnit->GetUV() || UV_DEAD == pUnit->GetUV())
        {
            if (UV_SOLDIER_1 == unitvalue || UV_SOLDIER_2 == unitvalue || UV_SOLDIER_3 == unitvalue)
            {
                pUnit->SetUV(unitvalue) ;
            }
            else
            {
                printf("CE7Rule::CreateUnit ERROR - 1\n") ;
            }
        }
        else
        {
            printf("CE7Rule::CreateUnit ERROR - 2\n") ;
        }
        
        CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(pUnit->GetCellID()) ;
        pCell->UpdateUV() ;

        CE7Town* pTown = s_pLogic->GetSelectTownInfo(townid) ;
        pTown->SetGold(pTown->GetGold()-UNIT_NEED_GOLD_ARRAY[unitvalue]) ;

        res = pUnit->GetID() ;
    }
    else
    {
        CE7Unit* pUnit = new CE7Unit() ;
        pUnit->Create(s_pLogic->GetNewUnitID(), unitvalue, countryid, townid, cellid) ;
        s_pLogic->AddUnitInfo(pUnit) ;

        pCell->SetUnitID(pUnit->GetID()) ;
        pCell->UpdateUV() ;

        CE7Town* pTown = s_pLogic->GetSelectTownInfo(townid) ;
        pTown->AddUnit(pUnit->GetID()) ;
        pTown->SetGold(pTown->GetGold()-UNIT_NEED_GOLD_ARRAY[unitvalue]) ;

        res = pUnit->GetID() ;
    }

//    if (-1 < res)
//    {
//        for (TOWN_INFO_LIST::iterator itr = s_pLogic->m_listTown.begin(); itr != s_pLogic->m_listTown.end(); ++itr)
//        {
//            (*itr)->Balance() ;
//        }
//    }

    if (CheckGameEnd())
    {
        s_pLogic->SetGameEnd() ;
    }

    return res ;
}

bool CE7Rule::CheckAttackWithCreate(int countryid, int townid, eUnitValue unitvalue, int cellid)
{
    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(cellid) ;

    // check neighbor.
    CE7Town* pTown = s_pLogic->GetSelectTownInfo(townid) ;
    bool flag = false ;
    for (int i = 0; i < 6; ++i)
    {
        if (NULL == pCell->GetNeighborPointer(i))
        {
            continue ;
        }
        int tempid = pCell->GetNeighborPointer(i)->GetID() ;
        for (CELL_ID_LIST::iterator itr = pTown->m_listCellIDs.begin(); itr != pTown->m_listCellIDs.end(); ++itr)
        {
            if (tempid == (*itr))
            {
                flag = true ;
                break ;
            }
        }
    }
    if (!flag)
    {
        // not neighbor.
        return false ;
    }

    pCell->UpdateUV() ;
    if (unitvalue <= pCell->GetUV())
    {
        return false ;
    }

    return true ;
}

int CE7Rule::AttackWithCreate(int countryid, int townid, eUnitValue unitvalue, int cellid)
{
    // create unit.
    CE7Unit* pUnit = new CE7Unit() ;
    pUnit->Create(s_pLogic->GetNewUnitID(), unitvalue, countryid, townid, cellid) ;
    pUnit->SetActionState(true) ;
    s_pLogic->AddUnitInfo(pUnit) ;

    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(cellid) ;

    // delete from old town.
    CE7Town* pOldTown = s_pLogic->GetSelectTownInfo(pCell->GetTownID()) ;
    if (NULL != pOldTown)
    {
        pOldTown->DelCell(cellid) ;
    }

    // delete from old country.
    CE7Country* pOldCountry = s_pLogic->GetSelectCountryInfo(pCell->GetCountryID()) ;
    pOldCountry->DelCell(pCell->GetID()) ;

    // add to town.
    pCell->SetUnitID(pUnit->GetID()) ;
    pCell->UpdateUV() ;

    CE7Town* pTown = s_pLogic->GetSelectTownInfo(townid) ;
    pTown->AddCell(cellid) ;
    pTown->SetGold(pTown->GetGold()-UNIT_NEED_GOLD_ARRAY[unitvalue]) ;
    
    // add to country.
    CE7Country* pCountry = s_pLogic->GetSelectCountryInfo(pTown->GetCountryID()) ;
    pCountry->AddCell(cellid) ;
    
    // add neighbor cell or town.
    for (int i = 0; i < 6; ++i)
    {
        if (NULL != pCell->GetNeighborPointer(i) &&
            countryid == pCell->GetNeighborPointer(i)->GetCountryID())
        {
            if (-1 == pCell->GetNeighborPointer(i)->GetTownID())
            {
                pTown->AddCell(pCell->GetNeighborPointer(i)->GetID()) ;
            }
            else if (pTown->GetID() != pCell->GetNeighborPointer(i)->GetTownID())
            {
                pTown->AttachTown(pCell->GetNeighborPointer(i)->GetTownID()) ;
            }
        }
    }

    if (NULL != pOldTown)
    {
        while (pOldTown->DetachTown()) ;
        if (1 == pOldTown->m_listCellIDs.size())
        {
            s_pLogic->DelSelectTownInfo(pOldTown->GetID()) ;
        }
    }

//    for (TOWN_INFO_LIST::iterator itr = s_pLogic->m_listTown.begin(); itr != s_pLogic->m_listTown.end(); ++itr)
//    {
//        (*itr)->Balance() ;
//    }

    if (CheckGameEnd())
    {
        s_pLogic->SetGameEnd() ;
    }

    return pUnit->GetID() ;
}

/////////////////////////////////

// .
bool CE7Rule::CheckAttachUnit(int unitid, int addunitid)
{
    return false ;
}

int CE7Rule::AttachUnit(int unitid, int addunitid)
{
    printf("attach unit \n") ;
    return unitid ;
}

bool CE7Rule::CheckAttachWithCreate(int unitid, eUnitValue uv)
{
    CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(unitid) ;
    if (UV_SOLDIER_1 == pUnit->GetUV())
    {
        if (UV_SOLDIER_1 == uv)
        {
//            pUnit->SetUV(UV_SOLDIER_2) ;
        }
        else if (UV_SOLDIER_2 == pUnit->GetUV())
        {
//            pUnit->SetUV(UV_SOLDIER_3) ;
        }
        else
        {
            printf("CE7Rule::CheckAttachWithCreate - 1 [%d] [%d] [%d]\n", unitid, pUnit->GetUV(), uv) ;
            return false ;
        }
    }
    else if (UV_SOLDIER_2 == pUnit->GetUV())
    {
        if (UV_SOLDIER_1 == uv)
        {
//            pUnit->SetUV(UV_SOLDIER_3) ;
        }
        else
        {
            printf("CE7Rule::CheckAttachWithCreate - 2 [%d] [%d] [%d]\n", unitid, pUnit->GetUV(), uv) ;
            return false ;
        }
    }
    else
    {
        printf("CE7Rule::CheckAttachWithCreate - 3 [%d] [%d] [%d]\n", unitid, pUnit->GetUV(), uv) ;
        return false ;
    }

    return true ;
}

bool CE7Rule::AttachWithCreate(int unitid, eUnitValue uv)
{
    if (!CheckAttachWithCreate(unitid, uv))
    {
        return false ;
    }

    CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(unitid) ;
    if (UV_SOLDIER_1 == pUnit->GetUV())
    {
        if (UV_SOLDIER_1 == uv)
        {
            pUnit->SetUV(UV_SOLDIER_2) ;
        }
        else if (UV_SOLDIER_2 == pUnit->GetUV())
        {
            pUnit->SetUV(UV_SOLDIER_3) ;
        }
    }
    else if (UV_SOLDIER_2 == pUnit->GetUV())
    {
        if (UV_SOLDIER_1 == uv)
        {
            pUnit->SetUV(UV_SOLDIER_3) ;
        }
    }

    CE7Town* pTown = s_pLogic->GetSelectTownInfo(pUnit->GetTownID()) ;
    pTown->SetGold(pTown->GetGold() - UNIT_NEED_GOLD_ARRAY[uv]) ;
    
    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(pUnit->GetCellID()) ;
    pCell->UpdateUV() ;

//    for (TOWN_INFO_LIST::iterator itr = s_pLogic->m_listTown.begin(); itr != s_pLogic->m_listTown.end(); ++itr)
//    {
//        (*itr)->Balance() ;
//    }

    return true ;
}

bool CE7Rule::CheckAttack(int countryid, int unitid, int cellid)
{
    printf("CE7Rule::CheckAttack: [%d][%d][%d]\n", countryid, unitid, cellid) ;

    CE7Unit* pSelUnit = s_pLogic->GetSelectUnitInfo(unitid) ;

    if (pSelUnit->IsActioned())
    {
        return false ;
    }

    int townid = pSelUnit->GetTownID() ;
    eUnitValue unitvalue = pSelUnit->GetUV() ;

    if (-1 == countryid || -1 == townid || -1 == unitvalue || -1 == cellid)
    {
        return false ;
    }
    
    if (UV_TOWER != unitvalue && UV_SOLDIER_1 != unitvalue && UV_SOLDIER_2 != unitvalue && UV_SOLDIER_3 != unitvalue)
    {
        return false ;
    }
    
    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(cellid) ;

    if (countryid == pCell->GetCountryID())
    {
        return false ;
    }

    pCell->UpdateUV() ;
    if (unitvalue <= pCell->GetUV())
    {
        return false ;
    }

    return true ;
}

bool CE7Rule::Attack(int countryid, int unitid, int cellid)
{
    printf("enter attack --- s\n") ;
    if (!CheckAttack(countryid, unitid, cellid))
    {
        return false ;
    }

    CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(unitid) ;
    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(cellid) ;

    int townid = pUnit->GetTownID() ;

    // delete from old town.
    CE7Town* pOldTown = s_pLogic->GetSelectTownInfo(pCell->GetTownID()) ;
    if (NULL != pOldTown)
    {
        pOldTown->DelCell(cellid) ;
    }

    // delete from old country.
    CE7Country* pOldCountry = s_pLogic->GetSelectCountryInfo(pCell->GetCountryID()) ;
    pOldCountry->DelCell(pCell->GetID()) ;

    // trans unit between two cell.
    CE7Cell* pOldCell = s_pLogic->ActiveMap()->GetSelectCellInfo(pUnit->GetCellID()) ;
    pOldCell->SetUnitID(-1) ;
    pUnit->SetCellID(pCell->GetID()) ;
    pUnit->SetShowState(true) ;
    pUnit->SetActionState(true) ;

    // add to town.
    pCell->SetUnitID(pUnit->GetID()) ;
    pCell->UpdateUV() ;

    CE7Town* pTown = s_pLogic->GetSelectTownInfo(townid) ;
    pTown->AddCell(cellid) ;
    
    // add to country.
    CE7Country* pCountry = s_pLogic->GetSelectCountryInfo(pTown->GetCountryID()) ;
    pCountry->AddCell(cellid) ;
    
    // add neighbor cell or town.
    for (int i = 0; i < 6; ++i)
    {
        if (NULL != pCell->GetNeighborPointer(i) &&
            countryid == pCell->GetNeighborPointer(i)->GetCountryID())
        {
            if (-1 == pCell->GetNeighborPointer(i)->GetTownID())
            {
                pTown->AddCell(pCell->GetNeighborPointer(i)->GetID()) ;
            }
            else if (pTown->GetID() != pCell->GetNeighborPointer(i)->GetTownID())
            {
                pTown->AttachTown(pCell->GetNeighborPointer(i)->GetTownID()) ;
            }
        }
    }
    
    if (NULL != pOldTown)
    {
        while (pOldTown->DetachTown()) ;
        if (1 == pOldTown->m_listCellIDs.size())
        {
            s_pLogic->DelSelectTownInfo(pOldTown->GetID()) ;
        }
    }

    printf("enter attack --- e\n") ;

//    for (TOWN_INFO_LIST::iterator itr = s_pLogic->m_listTown.begin(); itr != s_pLogic->m_listTown.end(); ++itr)
//    {
//        (*itr)->Balance() ;
//    }

    if (CheckGameEnd())
    {
        s_pLogic->SetGameEnd() ;
    }

    return true ;
}

bool CE7Rule::CheckMove(int countryid, int unitid, int cellid)
{
    printf("CE7Rule::CheckMove: [%d][%d][%d]\n", countryid, unitid, cellid) ;

    CE7Country* pCountry = s_pLogic->GetSelectCountryInfo(countryid) ;
    CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(unitid) ;
    CE7Cell* pOld = s_pLogic->ActiveMap()->GetSelectCellInfo(pUnit->GetCellID()) ;
    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(cellid) ;

    if (NULL == pCountry)
    {
        printf("CE7Rule::CheckMove NULL == pCountry\n") ;
        return false ;
    }

    if (NULL == pUnit)
    {
        printf("CE7Rule::CheckMove NULL == pUnit\n") ;
        return false ;
    }
    
    if (pUnit->IsActioned())
    {
        printf("CE7Rule::CheckMove pUnit->IsActioned()\n") ;
        return false ;
    }

    if (NULL == pOld)
    {
        printf("CE7Rule::CheckMove NULL == pOld\n") ;
        return false ;
    }

    if (NULL == pCell || -1 == pCell->GetCountryID())
    {
        printf("CE7Rule::CheckMove NULL == pCell || -1 == pCell->GetCountryID()\n") ;
        return false ;
    }

    if (-1 != pCell->GetUnitID())
    {
        printf("CE7Rule::CheckMove -1 == pCell->GetUnitID()\n") ;
        return false ;
    }

    return true ;
}

bool CE7Rule::Move(int countryid, int unitid, int cellid)
{
    if (!CheckMove(countryid, unitid, cellid))
    {
        return false ;
    }

    CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(unitid) ;
    CE7Cell* pOld = s_pLogic->ActiveMap()->GetSelectCellInfo(pUnit->GetCellID()) ;
    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(cellid) ;
    pUnit->SetCellID(cellid) ;
    pOld->SetUnitID(-1) ;
    pCell->SetUnitID(pUnit->GetID()) ;

    return true ;
}

bool CE7Rule::CheckGameEnd()
{
    // check game end.
    COUNTRY_INFO_LIST::iterator itr ;
    CE7Country* pCountry = s_pLogic->GetSelectCountryInfo(0) ;
    if (NULL == pCountry)
    {
        return false ;
    }

    printf("check game end : === %lu, %lu\n", pCountry->m_listCellIDs.size(), s_pLogic->ActiveMap()->m_listCells.size()) ;
    if (0 >= pCountry->m_listCellIDs.size())
    {
        m_iWinnerID = 1 ;
        return true ;
    }
    else if (s_pLogic->ActiveMap()->m_listCells.size() == pCountry->m_listCellIDs.size())
    {
        m_iWinnerID = 0 ;
        return true ;
    }

    return false ;
}


















